#pragma once
#include "Pocelain.h"
POCELAIN_NAMESPACE_BEGIN
class FlyControl : public Node3D {
public:
    FlyControl(IInput *input,Node3D *object)
        :mInput(input)
        ,mObject(object)
    {
    }
    virtual ~FlyControl()
    {
    }
    struct
    {
        int8_t up = 0;
        int8_t down= 0;
        int8_t left= 0;
        int8_t right= 0;
        int8_t forward= 0;
        int8_t back= 0;
        float pitchUp= 0.0f;
        float pitchDown= 0.0f;
        float yawLeft= 0.0f;
        float yawRight= 0.0f;
        int8_t rollLeft= 0;
        int8_t rollRight= 0;
    }moveState;
    Vector3 moveVector = Vector3( 0, 0, 0 );
    Vector3 rotationVector = Vector3( 0, 0, 0 );
    void update(Real delta)
    {
        if(mInput==nullptr || mObject==nullptr)
            return;
        if(mInput->getKey(EKeyCode::LeftShift)
                ||mInput->getKey(EKeyCode::RightShift)
                )
        {

        }

        moveState.forward = mInput->getKey(EKeyCode::W)?1:0;
        moveState.forward = moveState.forward|mInput->getKey(EKeyCode::Mouse0)?1:0;
        moveState.back = mInput->getKey(EKeyCode::S)?1:0;
        moveState.back = moveState.back|mInput->getKey(EKeyCode::Mouse1)?1:0;
        moveState.left = mInput->getKey(EKeyCode::A)?1:0;
        moveState.right = mInput->getKey(EKeyCode::D)?1:0;
        moveState.pitchUp = mInput->getKey(EKeyCode::UpArrow)?1:0;
        moveState.pitchDown = mInput->getKey(EKeyCode::DownArrow)?1:0;
        moveState.yawLeft = mInput->getKey(EKeyCode::LeftArrow)?1:0;
        moveState.yawRight = mInput->getKey(EKeyCode::RightArrow)?1:0;
        moveState.rollLeft = mInput->getKey(EKeyCode::Q)?1:0;
        moveState.rollRight = mInput->getKey(EKeyCode::E)?1:0;
        Vector3 moveVector,rotationVector;

        // pointer move
        {
            auto mousePosition = mInput->getMousePosition();
            auto scrollDelta = mInput->getMouseScrollDelta();
            auto windowSize = mInput->getWindowSize();
            auto halfWindowSize = windowSize/Vector2(2.0f,2.0f);
            mousePosition -= halfWindowSize;
            mousePosition /= halfWindowSize;
            moveState.yawLeft = -mousePosition.x;
            moveState.pitchDown = mousePosition.y;
        }


        bool forward = ( moveState.forward || ( autoForward && ! moveState.back ) ) ? true : false;
        moveVector.x = ( - moveState.left + moveState.right );
        moveVector.y = ( - moveState.down + moveState.up );
        moveVector.z = ( - forward + moveState.back );

        rotationVector.x = ( - moveState.pitchDown + moveState.pitchUp );
        rotationVector.y = ( - moveState.yawRight + moveState.yawLeft );
        rotationVector.z = ( - moveState.rollRight + moveState.rollLeft );

        auto moveMult = delta * movementSpeed;
        auto rotMult = delta * rollSpeed;

        mObject->translateX(moveVector.x * moveMult);
        mObject->translateY(moveVector.y * moveMult);
        mObject->translateZ(moveVector.z * moveMult);

        Quaternion tmpQuaternion;
        tmpQuaternion.set( rotationVector.x * rotMult, rotationVector.y * rotMult, rotationVector.z * rotMult, 1 );
        tmpQuaternion.normalize();
        mObject->setQuaternion(mObject->getQuaternion().multiply(tmpQuaternion));
    }

    // API
    Real movementSpeed = 10.0f;
    Real rollSpeed = 10.0f;

    bool dragToLook = false;
    bool autoForward = false;
protected:
    RefPtr<Node3D> mObject;
    RefPtr<IInput> mInput;
    const Real EPS = 0.000001;
    //this.mouseStatus = 0;

};
POCELAIN_NAMESPACE_END
